<template>
    <div class="take-photo">
        <div class="take-photo-wrap">
            <div class="take-photo-faker" v-if="imgUrl === '' || isClearPreviewImg">
                <p>照片</p>
            </div>

            <img :src="isClearPreviewImg ? '' : imgUrl" v-else/>
        </div>

        <div class="take-photo-btn">
            <Button type="primary" @click="showTakePhotoModal = true">拍照</Button>
        </div>

        <Modal
            :mask-closable="false"
            :width="600"
            :closable="false"
            :value="showTakePhotoModal"
            title="拍照"
            class="take-photo-modal">
            <div class="take-photo-video-wrap">
                <Spin v-if="!isShowVideo && !isShowCanvas"/>
                <video
                    autoplay
                    playsinline
                    ref="video"
                    v-show="isShowVideo && !isShowCanvas"
                />
                <img class="frame" src="/static/img/photo-wrap.png" />
                <canvas ref="canvas" width="600" height="480" v-show="isShowCanvas"/>
            </div>

            <p class="tip">请将正脸置于提示框内，并按提示完成操作。</p>

            <!-- 提示步骤 -->
            <div class="icon__wrap">
                <div>
                    <div
                        class="icon__wrap__content"
                        v-for="(icon, index) in icons.key"
                        :key="index">
                        <svg class="icon" aria-hidden="true">
                            <use :xlink:href="icon"></use>
                        </svg>
                        <p class="icon__wrap__text">{{icons.name[index]}}</p>
                    </div>
                </div>
            </div>

            <div slot="footer">
                <Button
                    type="ghost"
                    size="large"
                    @click="cancel">
                    {{isShowCanvas ? '重新拍摄' : '取消'}}
                </Button>

                <Button
                    type="primary"
                    size="large"
                    @click="checkPhoto"
                    :loading="isloading">
                    {{isShowCanvas ? '确定' : '拍摄'}}
                </Button>
            </div>
        </Modal>
  </div>
</template>

<script>
import util from '@/libs/util'
import file from '@/libs/file'
export default {
  data () {
    return {
      icons: {
        key: ['#icon-man-glasses', '#icon-man-hatless', '#icon-man-dark'],
        name: ['不能带眼镜', '不能带帽子', '光线不要太暗']
      },
      imgUrl: '', // img base64 url
      showTakePhotoModal: false, // 打开拍照弹窗
      video: null,
      canvas: null,
      isShowCanvas: false,
      isShowVideo: false,
      isloading: false
    }
  },

  props: {
    value: {
      type: [String, Number]
    },
    isClearPreviewImg: {
      type: Boolean,
      default: false
    },
    img: {
      type: String,
      default: ''
    }
  },

  computed: {
    face_id: { // 照片face_id
      get () {
        return this.value
      },

      set (value) {
        this.$emit('input', value)
      }
    }
  },

  watch: {
    showTakePhotoModal (value) {
      if (value) {
        if ((navigator && (
          (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) ||
                    navigator.getUserMedia ||
                    navigator.webkitGetUserMedia ||
                    navigator.mozGetUserMedia))) { // 浏览器支持摄像和拍照
          this.getUserMedia({audio: false, video: true}, (stream) => {
            this.isShowVideo = true
            this.video.srcObject = stream
          }, (err) => {
            console.log('拍照错误: ' + err.message)
          })
        } else {
          this.$Message.error('您的浏览器不支持拍照，请选择最新版的谷歌浏览器')
        }
      } else {
        if (this.video && this.video.srcObject) { // 关闭摄像头
          let stream = this.video.srcObject
          stream.getTracks().forEach(track => track.stop())
          stream = null
        }
        this.isShowVideo = false // 初始化video
        this.isShowCanvas = false // 初始化canvas
      }
    },

    isClearPreviewImg (value) {
      if (value) {
        this.imgUrl = ''
      }
    },

    img (value) {
      if (value !== '') {
        this.imgUrl = value
      }
    }
  },

  mounted () {
    this.video = this.$refs.video
    this.canvas = this.$refs.canvas
  },

  methods: {

    cancel () {
      if (this.isShowCanvas) {
        this.isShowCanvas = false
      } else {
        this.showTakePhotoModal = false
      }
    },

    /**
        * 确定照片合法性
        */
    async checkPhoto () {
      if (this.isShowCanvas) { // 校验照片合法性
        const dataurl = this.canvas.toDataURL('image/jpeg') // 图片转换成base 64
        const blob = util.dataURLtoBlob(dataurl)
        this.isloading = true
        try {
          const res = await file.accessControllUpload(blob)

          const { face_file_id } = res && res.data && res.data.result

          if (!face_file_id) { // 如果获取到face_file_id
            return
          }

          this.face_id = face_file_id
          this.imgUrl = dataurl
          this.showTakePhotoModal = false // 关闭拍照弹窗
          this.$Message.info('此照片可用于人脸识别开门')
        } catch (err) {
          const res = err.response
          if (res.data && res.data.err_msg) {
            this.$Message.error({content: res.data.err_msg, duration: 4})
          }
        } finally {
          this.isloading = false
        }
      } else { // 拍照
        this.isShowCanvas = true

        setTimeout(() => {
          const ctx = this.canvas.getContext('2d')
          ctx.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height)
        }, 100)
      }
    },

    getUserMedia (constrains, success, error) { // 兼容各个浏览器api
      if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        // 标准api
        navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error)
      } else if (navigator.webkitGetUserMedia) {
        // webkit内核浏览器
        navigator.webkitGetUserMedia(constrains).then(success).catch(error)
      } else if (navigator.mozGetUserMedia) {
        // Firefox浏览器
        // navagator.mozGetUserMedia(constrains).then(success).catch(error)
      } else if (navigator.getUserMedia) {
        // 旧版API
        navigator.getUserMedia(constrains).then(success).catch(error)
      }
    }
  }
}
</script>
<style lang='less' scope>
.take-photo {
    box-sizing: border-box;
    padding: 0 20px 0 40px;

    &-video-wrap {
        position: relative;
        width: 100%;
        height: 423px;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    &-wrap {
        width: 100%;
        height: 240px;
        border: 1px solid rgba(0,0,0, .2);

        >img {
            width: 100%;
            height: 100%;
        }
    }

    &-faker {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    &-btn {
        margin-top: 10px;
        width: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
    }
}

.frame {
    position: absolute;
    display: block;
    top: 20px;
    left: 140px;
    width: 300px;
    height: 383px;
    z-index: 1000;
}

.take-photo-modal {
    .tip {
        text-align: center;
        padding: 10px 0;
    }

    canvas {
        width: 100%;
        height: 423px;
    }

    .icon__wrap {
        display: flex;
        justify-content: center;

        > div {
            display: flex;
        }

        &__text {
            text-align: center;
            // position: relative;
            // top: -20px;
        }

        .icon {
            width: 80px;
            height: 50px;
        }
    }
}

</style>